function ngdomUI() {
	if (!ngdom.Engine) return;
	
	this.engine = ngdom.Engine;
	this.hud = { health: null, xp: null };
	this.xpColors = ['#dacaba'];
	this.hints = [
		{ keys: [37,38,39,40], wait: 5000, text: 'arrow keys to move', timer: null },
		{ keys: [32], wait: 15000, text: 'space to attack', timer: null },
		{ keys: false, wait: 25000, text: 'hold shift to run', timer: null }
	];
	this.messages = {
		levelUp: 'level up',
		buttons: {
			submit: 'Submit',
			cancel: 'Cancel',
			yes: 'Yes',
			no: 'No',
			okay: 'Okay'
		},
		labels: {
			email: 'Email:',
			password: 'Password:',
			confirm1: 'Confirm',
			confirm2: 'Password:',
			remember: 'Stay signed in?'
		},
		validation: {
			noEmail: 'You must enter an email address.',
			noPassword: 'You must enter a password.',
			passwordTooLong: 'The password is too long.',
			passwordMismatch: 'Your password confirmation doesn\'t match your password!'
		},
		menuContinue: {
			buttonContinue: 'Continue',
			buttonNewGame: 'New Game',
			buttonSignOut: 'Sign Out',
			buttonMore: ''
		},
		menuOptions: {
			buttonDeleteGame: 'Delete Saved Game',
			buttonBack: '',
			confirmDeleteGame: 'This will PERMANENTLY delete your saved progress and restart your game from the beginning. Continue anyway?',
			successDeleteGame: 'Your game save was successfully erased. You may now start fresh.',
			errorDeleteGame: 'Unexpected failure! Your game may or may not have been deleted.',
			waitDeleteGame: 'Deleting...'
		},
		menuNewGame: {
			buttonNewGame: 'New Game',
			buttonSignIn: 'Sign In',
			buttonCreateAccount: 'Create Account',
			confirmPlayWithoutSaving: 'If you play without signing in, you cannot save your game! Continue anyway?'
		},
		menuSignIn: {
			errorBadLogin: 'Bad username or password. Would you like to request a password reset?',
			errorServer: 'Unknown error. Check your internet connection, or try again later.',
			wait: 'Signing in...'
		},
		menuCreateAccount: {
			errorServer: 'Unknown error. Check your internet connection, or try again later.',
			success: 'Your account was successfully created. You are now logged in.',
			wait: 'Creating account...'
		},
		menuResetPassword: {
			caption: 'Want to reset your password? Enter the address you used to sign up.',
			success: 'Check your email to complete the password reset. If the message does not arrive, check your spam, and double-check your address.',
			wait: 'Please wait...'
		},
		menuChangePassword: {
			caption: 'Password Reset request received. Enter your new password below.',
			errorServer: 'Your password could not be changed! Your reset request might have expired. Would you like to try again?',
			success: 'Success! You can now sign in with your new password.',
			wait: 'Please wait...'
		}
	};
	
	this.hintText = $('<div id="hint" class="hint" style="display:none;"></div>').appendTo(this.engine.deck);
	this.statusText = $('<div id="status" style="display:none;"></div>').appendTo(this.engine.deck);
}
ngdomUI.prototype.initHints = function () {
	if (!ngdomData.savedata)
		$.each(this.hints, function (index, hint) {
			hint.timer = setTimeout('ngdom.Engine.ui.showHint('+index+');', hint.wait);
		});
};
ngdomUI.prototype.initHud = function (update) {
	if (typeof(update) == 'undefined') update = true;
	$('<img id="mute-button" src="image/'+(this.engine.mute ? '' : 'un')+'mute.gif" alt="" />')
		.appendTo(this.engine.deck)
		.data('mute_src', 'image/mute.gif')
		.data('unmute_src', 'image/unmute.gif')
		.click(function() {
			ngdom.Engine.mute = !ngdom.Engine.mute;
			$.cookie('ngdom-mute', ngdom.Engine.mute ? '1' : '0', { expires: 365 });
			
			if (ngdom.Engine.mute) soundManager.mute();
			else soundManager.unmute();
			
			this.src = $(this).data(ngdom.Engine.mute ? 'mute_src' : 'unmute_src');
		});
		
	var health_hud = $('<div id="health-hud"></div>').appendTo(this.engine.deck);
	this.hud.health = $('<div class="bar"></div>').appendTo(health_hud);
	this.hud.xp = $('<div class="bar"></div>').appendTo($('<div id="xp-hud"></div>').appendTo(this.engine.deck));
	
	if (update) this.updateHud(false);
};
ngdomUI.prototype.updateHud = function (animate, levelupCallback) {
	if (!this.hud.health) return;
	if (typeof(animate) == 'undefined') animate = true;
	if (!this.engine.fullyLoaded) animate = false;
	var that = this;
	
	this.hud.health.css('width', this.engine.player.health+'px');
	if (this.engine.player.maxHealth != $('#health-hud').width()) {
		if (animate) $('#health-hud').animate({ width: this.engine.player.maxHealth+'px' });
		else $('#health-hud').css({ width: this.engine.player.maxHealth+'px' });
	}
		
	if (this.engine.player.xp != this.hud.xp.width()) {
		if (animate) {
			if ($('#xp-numbers').length == 0)
				$('<h3 id="xp-numbers" style="display:none;"></h3>').appendTo(ngdom.Engine.deck);
				
			$('#xp-numbers')
				.text(this.hud.xp.width())
				.css({ position: 'absolute', left: '0px', top: '-43px', color: ngdom.Engine.ui.hud.xp.css('background-color'), 
					fontSize: '9pt', width: '30px', textAlign: 'center' })
				.fadeIn(100).delay(500).fadeOut(500)
				.animate({ top: '-50px' }, { duration: 1200, queue: false });
			this.hud.xp.animate({ width: this.engine.player.xp+'px' }, { 
				step: function (now, fx) { 
					$('#xp-numbers').text(''+Math.floor(now)).css('left', (now-15)+'px');
				}, 
				complete: function () { 
					if (ngdom.Engine.ui.hud.xp.width() == 100) {
						var bgcolor = ngdom.Engine.ui.hud.xp.css('background-color');
						$('<h3 style="display:none;">'+that.messages.levelUp+'</h3>').appendTo(ngdom.Engine.deck)
							.css({ position: 'absolute', left: '0px', top: '-45px', color: 'white', fontSize: '9pt' })
							.fadeIn(800).delay(1500).fadeOut(1800)
							.animate({ top: '-60px' }, { duration: 4100, queue: false });
						ngdom.Engine.ui.hud.xp
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ backgroundColor: '#ffffff' }, 30)		.delay(50)
							.animate({ backgroundColor: bgcolor }, 10)			.delay(50)
							.animate({ width: '0px' }, 10)
							.animate({ backgroundColor: ngdom.Engine.ui.xpColors[ngdom.Engine.player.level - 1] }, 10);
							
						if ($.isFunction(levelupCallback)) levelupCallback.call(this, animate);
					}
				}
			});
		}
		else {
			this.hud.xp.css({ 
				width: this.engine.player.xp+'px', 
				backgroundColor: ngdom.Engine.ui.xpColors[Math.min(ngdom.Engine.player.level - 1, ngdom.Engine.ui.xpColors.length - 1)] 
			});
			if (ngdom.Engine.ui.hud.xp.width() == 100 && $.isFunction(levelupCallback)) levelupCallback.call(this, animate);
		}
	}
	else {
		this.hud.xp.css({ backgroundColor: ngdom.Engine.ui.xpColors[ngdom.Engine.player.level - 1] });
	}
};
ngdomUI.prototype.menuContinue = function () {
	$('.menu').hide();
	if ($('#menu-load').length)
		$('#menu-load').show();
	else {
		$('<div id="menu-load" class="menu">' +
			'<div class="bg"></div>' +
			'<a id="btn-continue" class="button option1 default"><span></span> '+(ngdomData.savedata ? 
				ngdom.Engine.ui.messages.menuContinue.buttonContinue : 
				ngdom.Engine.ui.messages.menuContinue.buttonNewGame)+'</a>' +
			'<a id="btn-signout" class="button option2"><span></span> '+
				ngdom.Engine.ui.messages.menuContinue.buttonSignOut+'</a>' +
			'<a id="btn-options" class="button unobtrusive fr'+
				(ngdom.Engine.ui.messages.menuContinue.buttonMore ? '' : ' nolabel')+
				'"><span></span> '+
				ngdom.Engine.ui.messages.menuContinue.buttonMore+'</a>' +
		  '</div>')
		.appendTo(this.engine.portal);
		
		$('#btn-continue').click(function () {
			$('.menu').remove();
			if (ngdomData.savedata) {
				ngdom.Engine.begun = true;
				ngdom.Engine.startLoop();
			}
			else {
				ngdom.Engine.intro();
			}
			return false;
		});
		$('#btn-signout').click(function () {
			$.cookie('ngdom-auth', null);
			ngdomData.savedata = false;
			ngdomData.authorized = false;
			ngdom.Engine.loadGame();
			ngdom.Engine.ui.updateHud(false);
			ngdom.Engine.ui.menuNewGame();
			return false;
		});
		$('#btn-options').click(ngdom.Engine.ui.menuOptions);
	}
	return false;
};
ngdomUI.prototype.menuOptions = function () {
	$('.menu').hide();
	if ($('#menu-options').length)
		$('#menu-options').show();
	else {
		$('<div id="menu-options" class="menu">' +
			'<div class="bg"></div>' +
			'<a id="btn-delete" class="button cancel"><span></span> '+(ngdomData.savedata ? 
				ngdom.Engine.ui.messages.menuOptions.buttonDeleteGame : 
				ngdom.Engine.ui.messages.menuOptions.buttonNewGame)+'</a>' +
			'<a id="btn-options-back" class="button unobtrusive back fl'+
				(ngdom.Engine.ui.messages.menuOptions.buttonBack ? '' : ' nolabel')+
				'"><span></span> '+
				ngdom.Engine.ui.messages.menuOptions.buttonBack+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		
		$('#btn-delete').click(function () {
			ngdom.Engine.ui.confirm(ngdom.Engine.ui.messages.menuOptions.confirmDeleteGame, function (yes) {
				if (yes) {
					var request = $.post('game.php', { 
							action: 'delete'
						}, function (response) { 
							$('#btn-delete').removeClass('disabled'); 
							ngdom.Engine.ui.wait(false);
							ngdomData.savedata = false;
							if (!response)
								ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuOptions.errorDeleteGame);
							else 
								ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuOptions.successDeleteGame, function () {
									ngdomData.savedata = false;
									ngdom.Engine.loadGame();
									ngdom.Engine.ui.updateHud(false);
									$('.menu').remove();
									ngdom.Engine.ui.menuContinue();
								});
						});
					$('#btn-delete').addClass('disabled');
					ngdom.Engine.ui.wait(ngdom.Engine.ui.messages.menuOptions.waitDeleteGame, function () { 
						request.abort(); 
						$('#btn-delete').removeClass('disabled'); 
					}, 800);
				}
			});
			return false;
		});
		$('#btn-options-back').click(ngdom.Engine.ui.menuContinue);
	}
	return false;
};
ngdomUI.prototype.menuNewGame = function () {
	$('.menu').hide();
	if ($('#menu-new').length)
		$('#menu-new').show();
	else {
		$('<div id="menu-new" class="menu">' +
			'<div class="bg"></div>' +
			'<a id="btn-newgame" class="button option1"><span></span> '+ngdom.Engine.ui.messages.menuNewGame.buttonNewGame+'</a>' +
			'<a id="btn-signin" class="button option2"><span></span> '+ngdom.Engine.ui.messages.menuNewGame.buttonSignIn+'</a>' +
			'<a id="btn-signup" class="button option3"><span></span> '+ngdom.Engine.ui.messages.menuNewGame.buttonCreateAccount+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		
		$('#btn-newgame').click(function () {
			ngdom.Engine.ui.confirm(ngdom.Engine.ui.messages.menuNewGame.confirmPlayWithoutSaving, function (yes) {
				if (yes) {
					$('.menu').remove();
					ngdom.Engine.intro();
				}
			});
			return false;
		});
		$('#btn-signin').click(ngdom.Engine.ui.menuSignIn);
		$('#btn-signup').click(ngdom.Engine.ui.menuCreateAccount);
	}
	return false;
};
ngdomUI.prototype.menuSignIn = function () {
	$('.menu').hide();
	if ($('#menu-signin').length) {
		$('#menu-signin').show();
	}
	else {
		$('<div id="menu-signin" class="menu">' +
		  '<div class="bg"></div>' +
			'<form id="form-signin">' +
				'<label>'+ngdom.Engine.ui.messages.labels.email+' <input id="text-email" type="text" class="text" /></label>' +
				'<label>'+ngdom.Engine.ui.messages.labels.password+' <input id="text-pass" type="password" class="text" /></label>' +
				'<label class="yesno">'+ngdom.Engine.ui.messages.labels.remember+' <a id="yesno-remember" class="yesno-toggle yes">'+
					ngdom.Engine.ui.messages.buttons.yes+'</a></label>' +
				'<div class="clear"></div>' +
			'</form>' +
			'<a id="btn-signin-cancel" class="button cancel fl"><span></span> '+ngdom.Engine.ui.messages.buttons.cancel+'</a>' +
			'<a id="btn-signin-submit" class="button option2 submit default fr"><span></span> '+ngdom.Engine.ui.messages.buttons.submit+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		ngdom.Engine.ui.yesNoToggle();
		$('#btn-signin-cancel').click(function () {
			if (ngdom.Utils.queryValue('reset'))
				window.location = window.location.href.substr(0, window.location.href.indexOf('?'));
			else 
				ngdom.Engine.ui.menuNewGame();
		});
		$('#btn-signin-submit').click(function () {
			if ($(this).is('.disabled')) return false;
			if ($('#text-email').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noEmail);
				return false;
			}
			if ($('#text-pass').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noPassword);
				return false;
			}
			var request = $.ajax({ 
			  type: 'POST',
			  url: 'game.php', 
			  dataType: 'text', 
			  data: { 
				action: 'login', 
				user_email: $('#text-email').val(), 
				user_pass: $('#text-pass').val(),
				remember: $('#yesno-remember').data('value')
			  },
			  success: function (response) { 
				if (!response)
					ngdom.Engine.ui.confirm(ngdom.Engine.ui.messages.menuSignIn.errorBadLogin, function (yes) {
						if (yes) ngdom.Engine.ui.menuResetPassword();
					});
				else {
					if (ngdom.Utils.queryValue('reset'))
						window.location = window.location.href.substr(0, window.location.href.indexOf('?'));
					else {
						ngdomData.savedata = response == 'NOSAVE' ? false : response;
						ngdomData.authorized = true;
						ngdom.Engine.loadGame();
						ngdom.Engine.ui.updateHud(false);
						ngdom.Engine.ui.menuContinue();
					}
				}
			  },
			  error: function () {
			  	ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuSignIn.errorServer);
			  },
			  complete: function () {
				$('#btn-signin-submit').removeClass('disabled');
				ngdom.Engine.ui.wait(false);
			  }
			});
			$(this).addClass('disabled');
			ngdom.Engine.ui.wait(ngdom.Engine.ui.messages.menuSignIn.wait, function () { 
				request.abort(); 
				$('#btn-signin-submit').removeClass('disabled'); 
			}, 800);
		});
	}
	$('#text-email').focus();
	return false;
};
ngdomUI.prototype.menuCreateAccount = function () {
	$('.menu').hide();
	if ($('#menu-signup').length) {
		$('#menu-signup').show();
	}
	else {
		$('<div id="menu-signup" class="menu">' +
		  '<div class="bg"></div>' +
			'<form id="form-signup">' +
				'<label>'+ngdom.Engine.ui.messages.labels.email+' <input id="text-signup-email" type="text" class="text" /></label>' +
				'<label>'+ngdom.Engine.ui.messages.labels.password+' <input id="text-signup-pass" type="password" class="text" /></label>' +
				'<label class="multiline">'+ngdom.Engine.ui.messages.labels.confirm1+
					' <input id="text-signup-pass2" type="password" class="text" /><br />'+
					ngdom.Engine.ui.messages.labels.confirm2+
				' </label>' +
				'<div class="clear"></div>' +
			'</form>' +
			'<a id="btn-signup-cancel" class="button cancel fl"><span></span> '+ngdom.Engine.ui.messages.buttons.cancel+'</a>' +
			'<a id="btn-signup-submit" class="button option2 submit default fr"><span></span> '+ngdom.Engine.ui.messages.buttons.submit+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		$('#btn-signup-cancel').click(ngdom.Engine.ui.menuNewGame);
		$('#btn-signup-submit').click(function () {
			if ($(this).is('.disabled')) return false;
			if ($('#text-signup-email').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noEmail);
				return false;
			}
			if ($('#text-signup-pass').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noPassword);
				return false;
			}
			if ($('#text-signup-pass').val() != $('#text-signup-pass2').val()) {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.passwordMismatch);
				return false;
			}
			var request = $.post('game.php', { 
					action: 'createaccount', 
					user_email: $('#text-signup-email').val(), 
					user_pass: $('#text-signup-pass').val()
				}, function (response) { 
					$('#btn-signup-submit').removeClass('disabled');
					ngdom.Engine.ui.wait(false);
					if (!response || response.indexOf('ERROR:') === 0) 
						ngdom.Engine.ui.alert(response || ngdom.Engine.ui.messages.menuCreateAccount.errorServer);
					else {
						ngdomData.savedata = false;
						ngdomData.authorized = true;
						ngdom.Engine.ui.updateHud(false);
						ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuCreateAccount.success, 
							ngdom.Engine.ui.menuContinue);
					}
				});
			$(this).addClass('disabled');
			ngdom.Engine.ui.wait(ngdom.Engine.ui.messages.menuCreateAccount.wait, function () { 
				request.abort(); 
				$('#btn-signup-submit').removeClass('disabled'); 
			}, 800);
		});
	}
	$('#text-signup-email').focus();
	return false;
};
ngdomUI.prototype.menuResetPassword = function () {
	$('.menu').hide();
	if ($('#menu-resetpass').length) {
		$('#menu-resetpass').show();
	}
	else {
		$('<div id="menu-resetpass" class="menu">' +
		  '<div class="bg"></div>' +
		  	'<div class="caption">'+ngdom.Engine.ui.messages.menuResetPassword.caption+'</div>' +
			'<form id="form-resetpass">' +
				'<label>'+ngdom.Engine.ui.messages.labels.email+' <input id="text-reset-email" type="text" class="text" /></label>' +
				'<div class="clear"></div>' +
			'</form>' +
			'<a id="btn-reset-cancel" class="button cancel fl"><span></span> '+ngdom.Engine.ui.messages.buttons.cancel+'</a>' +
			'<a id="btn-reset-submit" class="button option2 submit default fr"><span></span> '+ngdom.Engine.ui.messages.buttons.submit+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		$('#btn-reset-cancel').click(ngdom.Engine.ui.menuNewGame);
		$('#btn-reset-submit').click(function () {
			if ($(this).is('.disabled')) return false;
			if ($('#text-reset-email').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noEmail);
				return false;
			}
			var request = $.post('game.php', { 
					action: 'resetpassword', 
					user_email: $('#text-reset-email').val()
				}, function (response) { 
					$('#btn-reset-submit').removeClass('disabled');
					ngdom.Engine.ui.wait(false);
					ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuResetPassword.success, ngdom.Engine.ui.menuNewGame);
				});
			$(this).addClass('disabled');
			ngdom.Engine.ui.wait(ngdom.Engine.ui.messages.menuResetPassword.wait, function () { 
				request.abort(); 
				$('#btn-reset-submit').removeClass('disabled'); 
			}, 800);
			return false;
		});
	}
	$('#text-reset-email').focus();
	return false;
};
ngdomUI.prototype.menuChangePassword = function () {
	$('.menu').hide();
	if ($('#menu-changepass').length) {
		$('#menu-changepass').show();
	}
	else {
		$('<div id="menu-changepass" class="menu">' +
		  '<div class="bg"></div>' +
		  	'<div class="caption">' + ngdom.Engine.ui.messages.menuChangePassword.caption + '</div>' +
			'<form id="form-changepass">' +
				'<label>' + 
					ngdom.Engine.ui.messages.labels.password +
					' <input id="text-change-pass" type="password" class="text" /></label>' +
				'<label class="multiline">' + 
					ngdom.Engine.ui.messages.labels.confirm1 +
					' <input id="text-change-pass2" type="password" class="text" /><br />' + 
					ngdom.Engine.ui.messages.labels.confirm2 +
				' </label>' +
				'<div class="clear"></div>' +
			'</form>' +
			'<a id="btn-change-cancel" class="button cancel fl"><span></span> '+ngdom.Engine.ui.messages.buttons.cancel+'</a>' +
			'<a id="btn-change-submit" class="button option2 submit default fr"><span></span> '+ngdom.Engine.ui.messages.buttons.submit+'</a>' +
		  '</div>')
		.appendTo(ngdom.Engine.portal);
		$('#btn-change-cancel').click(ngdom.Engine.ui.menuNewGame);
		$('#btn-change-submit').click(function () {
			if ($(this).is('.disabled')) return false;
			if ($('#text-change-pass').val() == '') {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.noPassword);
				return false;
			}
			if ($('#text-change-pass').val().length > 72) {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.passwordTooLong);
				return false;
			}
			if ($('#text-change-pass').val() != $('#text-change-pass2').val()) {
				ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.validation.passwordMismatch);
				return false;
			}
			var request = $.post('game.php', { 
					action: 'changepassword', 
					reset_token: ngdom.Utils.queryValue('reset'),
					new_pass: $('#text-change-pass').val()
				}, function (response) { 
					$('#btn-change-submit').removeClass('disabled');
					ngdom.Engine.ui.wait(false);
					if (!response)
						ngdom.Engine.ui.confirm(ngdom.Engine.ui.messages.menuChangePassword.errorServer, function(yes) {
								if (yes) ngdom.Engine.ui.menuResetPassword();
								else ngdom.Engine.ui.menuNewGame();
							});
					else 
						ngdom.Engine.ui.alert(ngdom.Engine.ui.messages.menuChangePassword.success, 
							ngdom.Engine.ui.menuSignIn);
				});
			$(this).addClass('disabled');
			ngdom.Engine.ui.wait(ngdom.Engine.ui.messages.menuChangePassword.wait, function () { 
				request.abort(); 
				$('#btn-change-submit').removeClass('disabled'); 
			}, 800);
			return false;
		});
	}
	$('#text-change-pass').focus();
	return false;
};
ngdomUI.prototype.alert = function (message, callback) {
	$('<div id="menu-alert" class="menu">' +
	  '<div class="bg"></div>' +
		'<div class="alert">' +
			message +
		'</div>' +
		'<a id="btn-alert-ok" class="button option2 okay default fl"><span></span> '+ngdom.Engine.ui.messages.buttons.okay+'</a>' +
	  '</div>')
	.appendTo(ngdom.Engine.portal);
	$('#btn-alert-ok').click(function () {
		$('#menu-alert').remove();
		if ($.isFunction(callback)) callback.call(ngdom.Engine.ui);
		return false;
	});
};
ngdomUI.prototype.confirm = function (message, callback) {
	$('<div id="menu-confirm" class="menu">' +
	  '<div class="bg"></div>' +
		'<div class="alert">' +
			message +
		'</div>' +
		'<a id="btn-confirm-yes" class="button option2 yes fl"><span></span> '+ngdom.Engine.ui.messages.buttons.yes+'</a>' +
		'<a id="btn-confirm-no" class="button cancel no fl"><span></span> '+ngdom.Engine.ui.messages.buttons.no+'</a>' +
	  '</div>')
	.appendTo(ngdom.Engine.portal);
	$('#btn-confirm-yes, #btn-confirm-no').click(function () {
		$('#menu-confirm').remove();
		if ($.isFunction(callback)) callback.call(ngdom.Engine.ui, this.id == 'btn-confirm-yes');
		return false;
	});
};
ngdomUI.prototype.wait = function (message, callback, delay) {
	if (message === false) {
		$('#menu-wait').remove();
		if (this.waitTimer) {
			clearTimeout(this.waitTimer);
			this.waitTimer = false;
		}
		return false;
	}
	
	if (!isNaN(delay)) {
		this.waitTimer = setTimeout(function() { ngdom.Engine.ui.wait(message, callback); }, delay);
		return false;
	}
	
	$('<div id="menu-wait" class="menu">' +
	  '<div class="bg"></div>' +
		'<div class="alert">' +
			message +
		'</div>' +
		'<a id="btn-wait-cancel" class="button cancel fl"><span></span> '+ngdom.Engine.ui.messages.buttons.cancel+'</a>' +
	  '</div>')
	.appendTo(ngdom.Engine.portal);
	$('#btn-wait-cancel').click(function () {
		$('#menu-wait').remove();
		if ($.isFunction(callback)) callback.call(ngdom.Engine.ui);
		return false;
	});
};
ngdomUI.prototype.yesNoToggle = function () {
	$('.yesno-toggle')
		.each(function () {
			$(this).data('value', $(this).html() == ngdom.Engine.ui.messages.buttons.yes ? 'Yes' : 'No');
		})
		.click(function () {
			if ($(this).data('value') == 'Yes') {
				$(this).data('value', 'No').removeClass('yes').addClass('no').html(ngdom.Engine.ui.messages.buttons.no);
			} else {
				$(this).data('value', 'Yes').removeClass('no').addClass('yes').html(ngdom.Engine.ui.messages.buttons.yes);
			}
		});
};
ngdomUI.prototype.showStatus = function (status, duration) {
	if ($('.hint:visible').length) return;
	if (typeof(duration) == 'undefined') duration = 2000;
	this.statusText.html(status).fadeIn(700).delay(duration).fadeOut(700);
};
ngdomUI.prototype.showHint = function (index) {
	this.hintText.html(this.hints[index].text)
		.fadeIn(700)
		.fadeTo(700, 0.5)
		.fadeTo(700, 1)
		.fadeTo(700, 0.5)
		.fadeTo(700, 1)
		.fadeTo(700, 0.5)
		.fadeTo(700, 1)
		.fadeTo(700, 0.5)
		.fadeTo(700, 1)
		.fadeOut(700);
	this.hints[index].timer = null;
};
ngdomUI.prototype.keydown = function (e) {
	if (e.which == 13) $('.button.default:visible').click();
	if (!ngdomData.savedata)
		$.each(ngdom.Engine.ui.hints, function (index, hint) {
			if ($.isArray(hint.keys) && $.inArray(e.which, hint.keys) > -1 && hint.timer != null) {
				clearTimeout(hint.timer);
				hint.timer = null;
			}
		});
};
ngdomUI.prototype.keyup = function () {
};